# -*- coding:utf-8 -*-
"""
请输入模块注释
"""
__author__ = "shu2015626"

import re
import datetime

from rest_framework import serializers
from django.contrib.auth import get_user_model
from django.conf import settings
from rest_framework.validators import UniqueValidator

from users.models import VerifyCode

User = get_user_model()
PATTERN_MOBILE = re.compile(settings.REGEX_MOBILE)


class SmsSerializer(serializers.Serializer):
    mobile = serializers.CharField(max_length=11, required=True)

    def validate_mobile(self, mobile):
        """
        自定义验证函数：验证手机号码
        注：函数名为，validate + _ + 需要验证的字段
        :param mobile:
        :return:
        """
        # 手机是否注册
        if User.objects.filter(mobile=mobile).count():
            raise serializers.ValidationError("用户已存在")

        # 验证手机号是否11位。单验证位数的原因是，万一输入12位，前11位刚好是手机号。这样也不对。
        if len(mobile) != 11:
            raise serializers.ValidationError("手机号码非法")

        # 验证手机号是否合法
        matcher = PATTERN_MOBILE.search(mobile)
        if not matcher:
            raise serializers.ValidationError("手机号码非法")

        # 验证手机验证码的发送频率
        x_seconds_ago = datetime.datetime.now() - datetime.timedelta(seconds=settings.VERIFY_CODE_SEND_FREQ)
        if VerifyCode.objects.filter(mobile=mobile, add_time__gt=x_seconds_ago).count():
            raise serializers.ValidationError("距离上一次发送未超过{freq}s".format(freq=settings.VERIFY_CODE_SEND_FREQ))

        return mobile


class UserRegisterSerializer(serializers.ModelSerializer):
    code = serializers.CharField(label="验证码", write_only=True, max_length=4, min_length=4, required=True,
                                 error_messages={
                                     'blank': "请输入验证码",
                                     'required': "请输入验证码",
                                     'min_length': "验证码格式错误",
                                     'max_length': "验证码格式错误",
                                 },
                                 help_text="验证码")
    username = serializers.CharField(label="用户名", required=True, allow_blank=False,
                                     validators=[UniqueValidator(queryset=User.objects.all(), message="用户已存在")],
                                     help_text="用户名")
    password = serializers.CharField(label="密码", style={'input_type': 'password'}, write_only=True, help_text="密码")

    def create(self, validated_data):
        """
        重载create方法，解决保存密码明文的问题
        """
        user = super().create(validated_data=validated_data)
        user.set_password(validated_data['password'])
        user.save()
        return user

    def validate_code(self, code):
        """考虑验证码需要验证几种类型"""
        # 1.验证码是否存在
        # 前端post过来的值都放在initial_data里
        verify_code_records = VerifyCode.objects.filter(mobile=self.initial_data['username']).order_by("-add_time")
        if verify_code_records:
            # 获取最近的一条验证码
            last_verify_code_record = verify_code_records[0]
            # 2.验证验证码是否过期
            x_seconds_ago = datetime.datetime.now() - datetime.timedelta(seconds=settings.VERIFY_CODE_EFFECTIVE_TIME)
            if last_verify_code_record.add_time < x_seconds_ago:
                raise serializers.ValidationError("验证码已过期")

            # 3.验证码是否和数据库中的一致
            if last_verify_code_record.code != code:
                raise serializers.ValidationError("验证码错误")

            # return code
            # 因为我们这里不需要将这个code再存在数据库中了，要的只是这个验证
            # 因此可以不返回这个验证完毕的code
        else:
            # 数据库中没有记录
            raise serializers.ValidationError("验证码错误")

    def validate(self, attrs):
        """
        作用在所有的字段之上。
        attrs是所有字段验证（调用自身的validate函数,如：validate_code）后返回的总的字典.

        可以自定义最终返回的数据
        """
        # 必须数据库要允许mobile为空，否则到不了这一步。逻辑上在`validate_mobile`的时候会抛出错误
        attrs['mobile'] = attrs['username']
        del attrs['code']
        return attrs

    class Meta:
        model = User
        fields = ("username", "code", "mobile", 'password')


class UserDetailSerializer(serializers.ModelSerializer):
    """
    用户详情序列话
    """
    class Meta:
        model = User
        fields = ("name", "gender", "birthday", "email", "mobile")